﻿ using PlayListSet.Comm;
using PlayListSet.Entity;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Linq;
using static PlayListSet.Comm.AppHelp;

namespace PlayListSet.UI
{
    public struct UIinfo
    {
        public double TOP { set; get; }
    }
    /// <summary>
    /// TimeListPanel.xaml 的交互逻辑
    /// </summary>
    public partial class TimeListPanel : UserControl, System.ComponentModel.INotifyPropertyChanged
    {
        public double TimePanelWidth//时间面板长度
        {
            get
            {
                return MainWindow.TimeCodeSeconds * 2;
            }
        }
        public Dictionary<string, ObservableCollection<PlayInfoBase>> DicList { get; set; }
        public Dictionary<string, UIinfo> DicUIInfo { get; set; }

        public TimeListPanel()
        {
            InitializeComponent();
            DicUIInfo = new Dictionary<string, UIinfo>();
            this.Loaded += TimeListPanel_Loaded;
            propertyUI = new PropertyUI();
            playCMDUI = new PlayCMDUI();

        }
        private bool init = false;
        private UIElement mouseLiveItem = null;
        public UIElement MouseLiveItem
        {
            set
            {
                if (mouseLiveItem != null)
                {

                    SetItemUIBoder(mouseLiveItem, false);
                }
                mouseLiveItem = value;

                if (mouseLiveItem != null)
                {

                    SetItemUIBoder(mouseLiveItem, true);
                }

            }
            get { return mouseLiveItem; }
        }

        private void SetItemUIBoder(UIElement uIElement, bool show)
        {
            SolidColorBrush solidColorBrush = show ? Brushes.LightSkyBlue : Brushes.Gray;
            Thickness thickness = show ? new Thickness(2) : new Thickness(1);
            if (MouseLiveItem.GetType() == typeof(PlayInfoItem))
            {
                PlayInfoItem playInfoItem = (PlayInfoItem)MouseLiveItem;
                playInfoItem.BorderBrush = solidColorBrush;
                playInfoItem.BorderThickness = thickness;
            }
            else
            {
                PlayCmdItem playInfoItem = (PlayCmdItem)MouseLiveItem;
                playInfoItem.BorderBrush = solidColorBrush;
                playInfoItem.BorderThickness = thickness;

            }
        }

        private PlayInfoBase selectItem = null;

        public PlayInfoBase SelectItem
        {
            get
            {
                return selectItem;
            }
            set
            {
                selectItem = value;

                if (selectItem == null)
                {
                    SelectPlayInfo = null; SelectPlayCmd = null;
                }
                else if (selectItem.GetType() == typeof(PlayInfo))
                {
                    SelectPlayInfo = (PlayInfo)selectItem;
                    propertyUI.DataContext = SelectPlayInfo;
                    PropertyInfoUI = propertyUI;

                }
                else if (selectItem.GetType() == typeof(PlayCmd))
                {
                    SelectPlayCmd = (PlayCmd)selectItem;
                    playCMDUI.DataContext = SelectPlayCmd;
                    PropertyInfoUI = playCMDUI;
                }
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectItem"));
            }
        }
        private PlayInfo selectPlayInfo; private PlayCmd selectPlayCmd;
        public PlayInfo SelectPlayInfo
        {
            get
            {
                return selectPlayInfo;
            }
            set
            {
                selectPlayInfo = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectPlayInfo"));
            }
        }
        public PlayCmd SelectPlayCmd
        {
            get
            {
                return selectPlayCmd;
            }
            set
            {
                selectPlayCmd = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectPlayCmd"));
            }
        }

        private PropertyUI propertyUI;
        private PlayCMDUI playCMDUI;
        private ContentControl propertyInfoUI = null;
        public ContentControl PropertyInfoUI
        {
            get
            {
                return propertyInfoUI;
            }
            set
            {
                propertyInfoUI = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PropertyInfoUI"));
            }
        }

        public double MouseLiveItemDownLeft = 0;

        public event PropertyChangedEventHandler PropertyChanged;

        private void TimeListPanel_Loaded(object sender, RoutedEventArgs e)
        {

            if (init == false)
            {
                init = true;
                this.DataContext = this;



                if (DicList == null) return;
                int row = 0;
                foreach (var key in DicList.Keys)
                {
                    var list = DicList[key];

                    var l = new Line()
                    {
                        X1 = 0,
                        X2 = TimePanelWidth,
                        Y1 = row * 50 + 90,
                        Y2 = row * 50 + 90,
                        Stroke = Brushes.Gray
                    };
                    listPanel.Children.Add(l);
                    TextBlock textBlock = new TextBlock() { Text = key };
                    Canvas.SetTop(textBlock, row * 50 + 57);
                    titlePanel.Children.Add(textBlock);
                    DicUIInfo.Add(key, new UIinfo { TOP = row * 50 + 50 });
                    foreach (var item in list)
                    {
                        CreatePlayInfoItem(item);
                    }
                    row++;
                    list.CollectionChanged += List_CollectionChanged;
                }
                listPanel.MouseLeave += (s, e1) =>
                {
                    if (MouseLiveItem != null && e1.LeftButton == MouseButtonState.Pressed)
                    {
                        MouseLiveItem = null;
                        if (DicList == null) return;
                        foreach (var key in DicList.Keys)
                        {
                            UpdateIitemOpacity(key);
                        }

                    }

                };

                Comm.AppControl.Instance.TimeCodePlayContorl.TimeCodeChanged += TimeCodePlayContorl_TimeCodeChanged;
                Comm.AppControl.Instance.TimeCodePlayContorl.OnTimeCodePlaybackState += TimeCodePlayContorl_OnTimeCodePlaybackState;
            }

        }

        private void TimeCodePlayContorl_OnTimeCodePlaybackState(NAudio.Wave.PlaybackState playbackState)
        {

        }

        private void TimeCodePlayContorl_TimeCodeChanged(TimeSpan currentTime)
        {
            if (LeftButton == MouseButtonState.Released)
                CurrentTimeCode = currentTime;
        }

        public void ClearDic()
        {
            foreach (var key in DicList.Keys)
            {
                var list = DicList[key];
                list.Clear();
            }
        }
        private void List_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                var ilist = e.NewItems;
                foreach (var item in ilist)
                {
                    PlayInfoBase playInfo = item as PlayInfoBase;

                    CreatePlayInfoItem(playInfo);
                }
                foreach (var key in DicList.Keys)
                {
                    UpdateIitemOpacity(key);
                }
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
            {
                var ilist = e.OldItems;
                foreach (var item in ilist)
                {
                    PlayInfoBase playInfo = item as PlayInfoBase;
                    for (int i = 0; i < listPanel.Children.Count; i++)
                    {
                        UIElement uIElement = listPanel.Children[i];
                        IPlayInfo playInfo1 = uIElement as IPlayInfo;
                        if (playInfo1 != null)
                        {
                            IPlayInfo playInfoItem = (IPlayInfo)uIElement;
                            if (playInfoItem.GetPlayInfoId() == playInfo.ID)
                            {
                                listPanel.Children.Remove(uIElement);
                                if (SelectItem != null && selectItem.ID == playInfo.ID)
                                {
                                    SelectItem = null;
                                }
                                break;
                            }
                        }

                    }
                }
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
            {
                List<UIElement> rs = new List<UIElement>();
                for (int i = 0; i < listPanel.Children.Count; i++)
                {
                    UIElement uIElement = listPanel.Children[i];
                    if (uIElement.GetType() == typeof(PlayInfoItem))
                    {
                        rs.Add(uIElement);
                    }
                    else if (uIElement.GetType() == typeof(PlayCmdItem))
                    {
                        rs.Add(uIElement);
                    }
                }
                for (int i = 0; i < rs.Count; i++)
                {
                    listPanel.Children.Remove(rs[i]);
                }
                SelectItem = null;
            }
        }
        public MouseButtonState LeftButton { set; get; } = MouseButtonState.Released;
        private UIinfo? GetUIInfo(string channelName)
        {
            if (DicUIInfo.ContainsKey(channelName))
            {
                return DicUIInfo[channelName];
            }
            return null;
        }
        private void CreatePlayInfoItem(PlayInfoBase playInfo)
        {
            var uiInfo = GetUIInfo(playInfo.Channel);
            if (playInfo.GetType() == typeof(PlayInfo))
            {
                PlayInfoItem playInfoItem = new PlayInfoItem();

                playInfoItem.SetBinding(PlayInfoItem.IsEnabledProperty, new Binding("IsEditModel") { Source = AppControl.Instance });
                playInfoItem.Width = (playInfo.EndTimeCode - playInfo.StartTimeCode) * 2;

                playInfoItem.PlayInfo = (PlayInfo)playInfo;
                Canvas.SetTop(playInfoItem, uiInfo.GetValueOrDefault().TOP);
                Canvas.SetLeft(playInfoItem, playInfo.StartTimeCode * 2);
                playInfoItem.MouseLeftButtonDown += (s, e1) =>
                {

                    CurrentTimeCode = TimeSpan.FromSeconds(Canvas.GetLeft(playInfoItem));
                    TickTextVis = Visibility.Visible;
                    MouseLiveItem = playInfoItem;
                    SelectItem = playInfo;
                    MouseLiveItemDownLeft = e1.GetPosition(playInfoItem).X;
                    e1.Handled = true;
                    //Console.WriteLine("MouseLeftButtonDown");
                };
                playInfoItem.MouseLeftButtonUp += (s, e1) =>
                {
                    MouseLiveItem = null;
                    UpdateIitemOpacity(playInfo.Channel);
                    //Console.WriteLine("MouseLeftButtonUp");
                };
                playInfoItem.OnDelete += (s, e) =>
                {
                    DicList[e.Channel].Remove(e);
                };
                playInfoItem.RightMouseEventHandler += (s, e) =>
                {
                    if (e.LeftButton == MouseButtonState.Pressed)
                    {
                        var playTime = (CurrentTimeCode.TotalSeconds - playInfo.StartTimeCode);
                        if (playTime > 10)
                        {
                            playInfo.EndTimeCode = playInfo.StartTimeCode + playTime;
                            playInfoItem.Width = playInfo.PlayTime * 2;
                            UpdateIitemOpacity(playInfo.Channel);
                        }
                    }
                };
                playInfo.StartTimeCodeChanged += (s, e) =>
                {
                    playInfoItem.Dispatcher.Invoke(() =>
                   {
                       Canvas.SetLeft(playInfoItem, e * 2);
                       UpdateIitemOpacity(playInfo.Channel);
                   });
                    //Console.WriteLine("PlayTimeChanged");
                };
                playInfo.PlayTimeChanged += (s, e) =>
                {
                    if (e < 0) return;
                    playInfoItem.Dispatcher.Invoke(() =>
                    {
                        playInfoItem.Width = e * 2;
                        UpdateIitemOpacity(playInfo.Channel);
                    });
                    //Console.WriteLine("PlayTimeChanged");
                };

                listPanel.Children.Add(playInfoItem);
            }
            else
            {
                PlayCmdItem playCmdItem = new PlayCmdItem();
              
                playCmdItem.SetBinding(PlayInfoItem.IsEnabledProperty, new Binding("IsEditModel") { Source = AppControl.Instance });
                playCmdItem.PlayCmd = (PlayCmd)playInfo;
                playInfo.EndTimeCode = playInfo.StartTimeCode + 17.5;
                playCmdItem.grid.DataContext = playCmdItem.PlayCmd;
                Canvas.SetTop(playCmdItem, uiInfo.GetValueOrDefault().TOP);
                Canvas.SetLeft(playCmdItem, playInfo.StartTimeCode * 2);

                playCmdItem.MouseLeftButtonDown += (s, e1) =>
                {

                    CurrentTimeCode = TimeSpan.FromSeconds(Canvas.GetLeft(playCmdItem));
                    TickTextVis = Visibility.Visible;
                    SelectItem = playInfo;
                    MouseLiveItem = playCmdItem;
                    MouseLiveItemDownLeft = e1.GetPosition(playCmdItem).X;
                };
                playCmdItem.MouseLeftButtonUp += (s, e1) =>
                {
                    MouseLiveItem = null;
                    UpdateIitemOpacity(playInfo.Channel);
                };
                playCmdItem.OnDelete += (s, e) =>
                {
                    DicList[e.Channel].Remove(e);
                };
                playInfo.StartTimeCodeChanged += (s, e) =>
                {
                    playCmdItem.Dispatcher.Invoke(() =>
                    {
                        Canvas.SetLeft(playCmdItem, e * 2);
                        UpdateIitemOpacity(playInfo.Channel);
                    });
                    //Console.WriteLine("PlayTimeChanged");
                };
                playInfo.PlayTimeChanged += (s, e) =>
                {
                    playCmdItem.Dispatcher.Invoke(() =>
                    {
                        playCmdItem.Width = e*2;
                        UpdateIitemOpacity(playInfo.Channel);
                    });

                };

                listPanel.Children.Add(playCmdItem);

            }


        }
        private void listPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //var point = e.GetPosition(listPanel);
            //CurrentTimeCode = TimeSpan.FromSeconds(point.X / 2);
            //e.Handled = true;

        }
        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {

            if (e.LeftButton == MouseButtonState.Pressed)
            {
                LeftButton = MouseButtonState.Pressed;
                if (MouseLiveItem == null)
                {
                    var point = e.GetPosition(listPanel);

                    CurrentTimeCode = TimeSpan.FromSeconds(point.X / 2);
                    TickTextVis = Visibility.Visible;
                }
                else
                {
                    var panelPoint = e.GetPosition(listPanel);
                    //var itemPoint = e.GetPosition(MouseLiveItem);
                    double left = panelPoint.X - MouseLiveItemDownLeft;
                    if (left < 0)
                        left = 0;
                    Canvas.SetLeft(MouseLiveItem, left);
                    if (MouseLiveItem.GetType() == typeof(PlayInfoItem))
                    {
                        PlayInfoItem playInfoItem = (PlayInfoItem)MouseLiveItem;
                        playInfoItem.PlayInfo.EndTimeCode = left / 2 + (playInfoItem.PlayInfo.EndTimeCode - playInfoItem.PlayInfo.StartTimeCode);
                        playInfoItem.PlayInfo.StartTimeCode = left / 2;
                    }
                    else
                    {
                        PlayCmdItem playInfoItem = (PlayCmdItem)MouseLiveItem;
                        playInfoItem.PlayCmd.EndTimeCode = left / 2 + (playInfoItem.PlayCmd.EndTimeCode - playInfoItem.PlayCmd.StartTimeCode);
                        playInfoItem.PlayCmd.StartTimeCode = left / 2;

                    }

                    tickText.Text = TimeSpan.FromSeconds(left / 2).ToString();
                    CurrentTimeCode = TimeSpan.FromSeconds(left / 2);

                    TickTextVis = Visibility.Visible;
                }

            }
            else
            {
                TickTextVis = Visibility.Hidden;
                //seek
                if (LeftButton == MouseButtonState.Pressed)
                {
                    AppControl.Instance.TimeCodePlayContorl.Seek(CurrentTimeCode);
                    LeftButton = MouseButtonState.Released;
                }

            }
            mousePoint = e.GetPosition(listPanel);
            // Console.WriteLine(mousePoint.Y);


        }

        Point mousePoint = new Point();

        public void UpdateIitemOpacity(string key)
        {
            if (DicList == null) return;
            if (!DicList.ContainsKey(key)) return;
            var list = DicList[key];
            for (int i = 0; i < list.Count; i++)
            {
                double o = 1;
                var x = list[i];
                for (int j = 0; j < list.Count; j++)
                {
                    var y = list[j];
                    if (x.ID != y.ID)
                    {
                        //Console.WriteLine(x.Name);
                        //Console.WriteLine(x.StartTimeCode + ":" + x.EndTimeCode);
                        //Console.WriteLine(y.Name);
                        //Console.WriteLine(y.StartTimeCode + ":" + y.EndTimeCode);
                        //Console.WriteLine((x.StartTimeCode > y.StartTimeCode && x.StartTimeCode < y.EndTimeCode));
                        //Console.WriteLine((x.EndTimeCode > y.StartTimeCode && x.EndTimeCode < y.EndTimeCode));

                        if (
                           (x.StartTimeCode > y.StartTimeCode && x.StartTimeCode < y.EndTimeCode)
                        || (x.EndTimeCode > y.StartTimeCode && x.EndTimeCode < y.EndTimeCode)
                        || (y.StartTimeCode > x.StartTimeCode && y.StartTimeCode < x.EndTimeCode)
                        || (y.EndTimeCode > x.StartTimeCode && y.EndTimeCode < x.EndTimeCode)
                        )
                        {
                            o = 0.5;
                            break;
                        }
                    }
                }
                x.Opacity = o;

            }

        }

        private Visibility tickTextVis = Visibility.Hidden;
        public Visibility TickTextVis
        {
            set
            {
                if (tickTextVis != value)
                {
                    tickTextVis = value;
                    PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs("TickTextVis"), null, null);
                }
            }
            get
            {
                return tickTextVis;
            }
        }
        private TimeSpan currentTimeCode = TimeSpan.Zero;
        public TimeSpan CurrentTimeCode
        {
            set
            {
                currentTimeCode = value;
                PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs("CurrentTimeCode"), null, null);
            }
            get
            {
                return currentTimeCode;
            }
        }


        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {

            Paste();
        }


        private void Paste()
        {
            try
            {
                var pase = AppHelp.PasteFromClipboard();
                if (pase == null) return;
                if (DicList == null) return;
                var list = DicList.Keys.ToList();
                var i = (int)((mousePoint.Y) / 50d);
                i--;
                if (i < 0) return;
                if (i >= list.Count) return;
                var chandel = AppControl.Instance.ChannelInfos.Where(t => t.ChannelName == list[i]).FirstOrDefault();
                if (pase.CopyType == AppHelp.CopyType.PlayInfoItem)
                {
                    var data = Newtonsoft.Json.JsonConvert.DeserializeObject<PlayInfo>(pase.Data + "");
                    data.UpdateId();

                    var t = data.EndTimeCode - data.StartPlayTime;
                    data.StartTimeCode = mousePoint.X / 2;
                    data.EndTimeCode = data.StartTimeCode + t;


                    if (chandel != null)
                    {
                        data.ChannelType = chandel.ChannelType;
                        data.Channel = chandel.ChannelName;
                        data.ChannelInfo = new Size(chandel.SizeWidth, chandel.SizeHeight);
                    }

                    DicList[list[i]].Add(data);
                    // CreatePlayInfoItem(data);
                }
                else if (pase.CopyType == AppHelp.CopyType.PlayInfoItem)
                {
                    var data = Newtonsoft.Json.JsonConvert.DeserializeObject<PlayCmd>(pase.Data + "");
                    data.StartTimeCode = mousePoint.X / 2;
                    data.UpdateId();
                    if (chandel != null)
                    {
                        data.ChannelType = chandel.ChannelType;
                        data.Channel = chandel.ChannelName;
                    }

                    //CreatePlayInfoItem(data);
                    DicList[list[i]].Add(data);

                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private void UserControl_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.V && leftCtrl)
            {

                Paste(); e.Handled = true;
            }
            else if (e.Key == Key.C && leftCtrl)
            {
                if (AppControl.Instance.CopySelect != null)
                {
                    try
                    {
                        if (AppControl.Instance.CopySelect is PlayInfo playInfo)
                        {
                            AppHelp.CopyToClipboard(new AppHelp.ATSCopyClipboardData()
                            { CopyType = AppHelp.CopyType.PlayInfoItem, Data = playInfo });
                            e.Handled = true;
                        }
                        else if (AppControl.Instance.CopySelect is PlayCmd playCmd)
                        {
                            AppHelp.CopyToClipboard(new AppHelp.ATSCopyClipboardData()
                            { CopyType = AppHelp.CopyType.PlayCmd, Data = playCmd });
                            e.Handled = true;
                        }

                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }

                }
            }
            else if (e.Key == Key.LeftCtrl)
            {
                leftCtrl = true;
            }
            else if (e.Key == Key.Delete)
            {
                if (AppControl.Instance.CopySelect != null)
                {
                    var copySelect = AppControl.Instance.CopySelect;
                    foreach (var key in DicList.Keys)
                    {
                        var list = DicList[key];

                        if (list.Remove(copySelect))
                        {
                            AppControl.Instance.CopySelect = null;
                            break;
                        }

                    }
                    e.Handled = true;
                }

            }
        }
        bool leftCtrl = false;
        private void UserControl_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.LeftCtrl)
            {
                leftCtrl = false;
            }
        }

        private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.Focus();

        }

        private void MenuItem_Click_1(object sender, RoutedEventArgs e)
        {

            if (DicList == null) return;
            var list = DicList.Keys.ToList();
            var i = (int)((mousePoint.Y) / 50d);
            i--;
            //if (i < 0) return;
            //if (i >= list.Count) return;
            //var chandel = AppControl.Instance.ChannelInfos.Where(t => t.ChannelName == list[i]).FirstOrDefault();
             MainWindow.MainWindowStatic.OPenNew(i);
        }

        private void listPanel_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            var point = e.GetPosition(listPanel);
            Task.Factory.StartNew(() => {
                Thread.Sleep(100);
                CurrentTimeCode = TimeSpan.FromSeconds(point.X / 2);
                Console.WriteLine(1);
            });
        }

        public void SetContextMenu(bool state)
        {
            if (state)
            {
                titleContextMenu.IsEnabled = true;
                titleContextMenu.Visibility = Visibility.Visible;
                titleContextMenu.IsOpen = false;
            }
            else
            {
                titleContextMenu.IsEnabled = false;
                titleContextMenu.Visibility = Visibility.Collapsed;
                titleContextMenu.IsOpen = false;
            }

        }
    }
}